package org.locker.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.locker.common.core.utils.MapstructUtils;
import org.locker.common.core.utils.StringUtils;
import org.locker.common.mybatis.core.page.PageQuery;
import org.locker.domain.Device;
import org.locker.domain.DeviceGrid;
import org.locker.domain.bo.DeviceGridBo;
import org.locker.domain.enums.DeviceGridStatusEnum;
import org.locker.domain.enums.DeviceStatusEnum;
import org.locker.domain.vo.DeviceGridVo;
import org.locker.mapper.DeviceGridMapper;
import org.locker.netty.MachineService;
import org.locker.service.IDeviceGridService;
import org.locker.service.IDeviceService;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * 设备格子信息Service业务层处理
 *
 * @author winnie
 * @date 2023-10-11
 */
@RequiredArgsConstructor(onConstructor_ = {@Lazy})
@Service
@Transactional
public class DeviceGridServiceImpl extends ServiceImpl<DeviceGridMapper, DeviceGrid> implements IDeviceGridService {

    private final DeviceGridMapper baseMapper;
    private final IDeviceService deviceService;
    private final MachineService machineService;

    /**
     * 查询设备格子信息
     */
    @Override
    public DeviceGridVo queryById(Long deviceGridId) {
        return baseMapper.selectVoById(deviceGridId);
    }

    /**
     * 查询设备格子信息列表
     */
    @Override
    public Page<DeviceGridVo> queryPageList(DeviceGridBo bo, PageQuery pageQuery) {
        return baseMapper.getList(pageQuery.build(), bo);
    }

    /**
     * 查询设备格子信息列表
     */
    @Override
    public List<DeviceGridVo> queryList(DeviceGridBo bo) {
        LambdaQueryWrapper<DeviceGrid> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<DeviceGrid> buildQueryWrapper(DeviceGridBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<DeviceGrid> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getPositionId() != null, DeviceGrid::getPositionId, bo.getPositionId());
        lqw.eq(bo.getSpecCode() != null, DeviceGrid::getSpecCode, bo.getSpecCode());
        lqw.eq(bo.getDeviceId() != null, DeviceGrid::getDeviceId, bo.getDeviceId());
        lqw.eq(StringUtils.isNotBlank(bo.getDeviceNo()), DeviceGrid::getDeviceNo, bo.getDeviceNo());
        lqw.like(StringUtils.isNotBlank(bo.getName()), DeviceGrid::getName, bo.getName());
        lqw.eq(StringUtils.isNotBlank(bo.getNumber()), DeviceGrid::getNumber, bo.getNumber());
        lqw.eq(StringUtils.isNotBlank(bo.getSerialNo()), DeviceGrid::getSerialNo, bo.getSerialNo());
        lqw.eq(StringUtils.isNotBlank(bo.getSerialIndex()), DeviceGrid::getSerialIndex, bo.getSerialIndex());
        lqw.eq(StringUtils.isNotBlank(bo.getMacNo()), DeviceGrid::getMacNo, bo.getMacNo());
        lqw.eq(StringUtils.isNotBlank(bo.getGridType()), DeviceGrid::getGridType, bo.getGridType());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), DeviceGrid::getStatus, bo.getStatus());
        return lqw;
    }

    /**
     * 新增设备格子信息
     */
    @Override
    public Boolean insertByBo(DeviceGridBo bo) {
        DeviceGrid add = MapstructUtils.convert(bo, DeviceGrid.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            statisticsGridNumber(add.getDeviceNo());
            bo.setDeviceGridId(add.getDeviceGridId());
        }
        return flag;
    }

    /**
     * 修改设备格子信息
     */
    @Override
    public Boolean updateByBo(DeviceGridBo bo) {
        DeviceGrid update = MapstructUtils.convert(bo, DeviceGrid.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(DeviceGrid entity) {
        //做一些数据校验,如唯一约束
    }

    /**
     * 批量删除设备格子信息
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //做一些业务上的校验,判断是否需要校验
        }
        Long id = ids.stream().findFirst().orElse(null);
        if (id == null) {
            return false;
        }
        DeviceGridVo deviceGridVo = baseMapper.selectVoById(id);
        boolean b = baseMapper.deleteBatchIds(ids) > 0;
        if (b) {
            statisticsGridNumber(deviceGridVo.getDeviceNo());
        }
        return b;
    }


    @Override
    public List<DeviceGrid> selectByDeviceId(Long deviceId) {
        return baseMapper.selectJoinInfoList(deviceId);
    }

    @Override
    public Boolean locker(Long id) {
        return this.update(Wrappers.<DeviceGrid>lambdaUpdate()
            .set(DeviceGrid::getStatus, DeviceGridStatusEnum.locker.getCode())
            .eq(DeviceGrid::getDeviceGridId, id));
    }

    @Override
    public Boolean unlock(Long id) {
        return this.update(Wrappers.<DeviceGrid>lambdaUpdate()
            .set(DeviceGrid::getStatus, DeviceGridStatusEnum.unlock.getCode())
            .eq(DeviceGrid::getDeviceGridId, id));
    }

    @Override
    public void open(Long[] deviceGridIds) {
        List<DeviceGrid> deviceGrids = this.listByIds(Arrays.asList(deviceGridIds));
        for (DeviceGrid deviceGrid : deviceGrids) {
            Device device = deviceService.queryByDeviceNo(deviceGrid.getDeviceNo());
            if (device != null) {
                String status = device.getStatus();
                if (status.equals(DeviceStatusEnum.offline.getCode())) {
                    throw new RuntimeException("设备已下线，无法发送指令，请线下操作设备。");
                }
            }
            machineService.controlOpen(deviceGrid.getDeviceNo(), deviceGrid.getDeviceGridId(), "");
        }
    }

    /**
     * 统计格子数量
     *
     * @param deviceNo 设备号
     */
    private void statisticsGridNumber(String deviceNo) {
        long count = this.count(Wrappers.<DeviceGrid>lambdaQuery().eq(DeviceGrid::getDeviceNo, deviceNo));
        deviceService.update(Wrappers.<Device>lambdaUpdate()
            .set(Device::getGardNum, count).eq(Device::getDeviceNo, deviceNo));
    }
}
